package com.genius.controller;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.genius.annotation.PreFuncAuth;
import com.genius.config.MinioConfig;
import com.genius.constant.DataStatusConstants;
import com.genius.core.JSONResult;
import com.genius.enums.ResponseType;
import com.genius.file.bo.*;
import com.genius.file.pojo.File;
import com.genius.service.FileService;
import com.genius.utils.MinioUtils;
import com.genius.utils.PageUtils;
import com.genius.utils.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "file")
@Api(value = "文件管理相关接口", tags = {"用于文件管理的接口"})
public class FileController {

    @Autowired
    private MinioUtils minioUtils;
    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private FileService fileService;

    @PostMapping("/selectFileByPage")
    @ApiOperation(value = "查询文件（分页查询）",notes = "查询文件分页数据", httpMethod = "POST")
    @PreFuncAuth("SYS:FILE:SELECT")
    public JSONResult selectFileByPage(@Valid @RequestBody SelectFileByPageBO selectFileByPageBO) {
        int pageNum = selectFileByPageBO.getPageNum();
        int pageSize = selectFileByPageBO.getPageSize();
        File file = JSONUtil.parse(selectFileByPageBO).toBean(File.class);
        file.setCreateBy(SecurityUtils.getUsername());
        PageUtils.startPage(pageNum,pageSize);
        List<File> dictList= fileService.selectFileByPage(file);
        Map<String,Object> result = PageUtils.getResultTableData(dictList);
        return JSONResult.ok(result);
    }

    @PostMapping("/uploadAvatar")
    @ApiOperation(value = "头像上传",notes = "头像上传返回url", httpMethod = "POST")
    public JSONResult upload(@RequestParam("file") MultipartFile multipartFile) {
        String contentType = multipartFile.getContentType();
        long fileSize = multipartFile.getSize();
        if(fileSize / 1024 / 1024 > 2){
            return JSONResult.errorCustom(ResponseType.IMAGE_MAX_SIZE_2MB_ERROR);
        }
        assert contentType != null;
        if(!contentType.equals("image/jpeg")){
            return JSONResult.errorCustom(ResponseType.IMAGE_FORMATTER_FAILED);
        }
        String objectName = minioUtils.upload(multipartFile);
        if (null != objectName) {
            Map<String, Object> result = new HashMap<>();
            result.put("url",(minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName));
            File file = new File();
            Long fileId = IdUtil.getSnowflake().nextId();
            file.setFileId(fileId);
            file.setFileName(multipartFile.getOriginalFilename());
            file.setFileUrl(objectName);
            file.setFileType("2");
            file.setFileSize(fileSize);
            file.setCreateBy(SecurityUtils.getUsername());
            fileService.insertFile(file);
            return JSONResult.ok(result);
        }
        return JSONResult.errorCustom(ResponseType.FILE_UPLOAD_FAILED);
    }

    @GetMapping("/preview")
    @ApiOperation(value = "获取预览地址",notes = "根据文件路径获取预览地址", httpMethod = "GET")
    @PreFuncAuth("SYS:FILE:PREVIEW")
    public JSONResult preview(@RequestParam("fileName") String fileName) {
        Map<String, Object> result = new HashMap<>();
        result.put("fileName",minioUtils.preview(fileName));
        return JSONResult.ok(result);
    }

    @GetMapping("/download")
    @ApiOperation(value = "下载文件",notes = "根据文件路径下载文件", httpMethod = "GET")
    @PreFuncAuth("SYS:FILE:DOWNLOAD")
    public void download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
        minioUtils.download(fileName,res);
    }

    @PostMapping("/deleteFileByIds")
    @ApiOperation(value = "删除文件",notes = "删除文件", httpMethod = "POST")
    @PreFuncAuth("SYS:FILE:DELETE")
    public JSONResult deleteFileByIds(@Valid @RequestBody DeleteFileByIdsBO deleteFileByIdsBO) {
        int rows = fileService.deleteFileByIds(deleteFileByIdsBO.getFileIds());
        if(rows > 0){
            for(Long fileId:deleteFileByIdsBO.getFileIds()){
                File file = fileService.selectFileById(fileId);
                minioUtils.remove(file.getFileUrl());
            }
        }
        Map<String,Object> result = new HashMap<>();
        result.put("rows",rows);
        return JSONResult.ok(result);
    }

    @PostMapping("/getUploadUrl")
    @ApiOperation(value = "获取直传地址",notes = "获取直传地址", httpMethod = "POST")
    @PreFuncAuth("SYS:FILE:UPLOAD")
    public JSONResult getUploadUrl(@Valid @RequestBody UploadFileBO uploadFileBO){
        String originalFilename = uploadFileBO.getFileName();
        String fileName = UUID.fastUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = DateUtil.format(new Date(),"yyyy-MM/dd") + "/" + fileName;
        String url = minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName;
        File file = new File();
        Long fileId = IdUtil.getSnowflake().nextId();
        file.setFileId(fileId);
        file.setFileName(originalFilename);
        file.setFileUrl(objectName);
        file.setFileType(uploadFileBO.getFileType());
        file.setFileSize(uploadFileBO.getFileSize());
        file.setDelFlag(DataStatusConstants.DISABLE);
        file.setCreateBy(SecurityUtils.getUsername());
        fileService.insertFile(file);
        // 直传需要的url地址
        String uploadUrl = minioUtils.getUploadUrl(fileName);
        Map<String,Object> result = new HashMap<>();
        result.put("url",url);
        result.put("fileId",fileId.toString());
        result.put("uploadUrl",uploadUrl);
        return JSONResult.ok(result);
    }

    @PostMapping("/uploadSucceed")
    @ApiOperation(value = "直传完成确认",notes = "直传完成确认", httpMethod = "POST")
    @PreFuncAuth("SYS:FILE:UPLOAD")
    public JSONResult uploadSucceed(@Valid @RequestBody UnDeleteFileByIdsBO unDeleteFileByIdsBO){
        fileService.unDeleteFileByIds(unDeleteFileByIdsBO.getFileIds());
        return JSONResult.ok();
    }

    @PostMapping("/getDownloadUrl")
    @ApiOperation(value = "获取下载地址",notes = "获取下载地址", httpMethod = "POST")
    @PreFuncAuth("SYS:FILE:UPLOAD")
    public JSONResult getDownloadUrl(@Valid @RequestBody DownloadFileBO downloadFileBO){
        Long fileId = downloadFileBO.getFileId();
        File file = fileService.selectFileById(fileId);
        // 下载需要的url地址
        String downloadUrl = minioUtils.getDownloadUrl(file.getFileUrl());
        Map<String,Object> result = new HashMap<>();
        result.put("downloadUrl",downloadUrl);
        return JSONResult.ok(result);
    }
}